# -*- encoding: iso-8859-1 -*-
from picshell.engine.core.PicEngine import PicEngine
from picshell.engine.core.PicThreadEngine import PicThreadEngine
from picshell.engine.util.Format import Format
from picshell.monitors.DeviceStateMonitors import DeviceSourceStateMonitor
from picshell.monitors.DeviceStateMonitors import DeviceTargetStateMonitor
from picshell.monitors.RegisterUpdater import RegisterUpdater
from picshell.parser.AnnotationParser import AnnotationParser
from picshell.parser.AnnotationParser import watchInfo
from picshell.parser.JalV2AsmParser import JalV2AsmParser
from picshell.parser.JalV2Parser import JalV2Parser
from picshell.ui.Context import Context
from picshell.ui.config.PreferencesDialog import PreferencesDialog
from picshell.ui.debug.comp.ButtonHandler import MpdHandler
from picshell.ui.debug.comp.ButtonHandler import MpuHandler
from picshell.ui.debug.comp.ButtonHandler import PotHandler
from picshell.ui.debug.comp.ButtonHandler import PpdHandler
from picshell.ui.debug.comp.ButtonHandler import PpuHandler
from picshell.ui.debug.comp.CLED import CLED
from picshell.ui.debug.comp.Counter import UpDownCounter
from picshell.ui.debug.comp.Dual7Seg import Dual7Seg
from picshell.ui.debug.comp.LCD import LCD
from picshell.ui.debug.comp.LED import LED
from picshell.ui.debug.comp.Watch import Watch
from picshell.ui.edit.EditorUtil import EditorUtil
from picshell.ui.edit.FindDialog import FindDialog
from picshell.util.AssertUtil import AssertUtil
from picshell.util.DocHelper import AsmDocHelp
from picshell.util.FileUtil import FileUtil
from picshell.engine.core.pics import PicFactory
from wx import gizmos
from wx._gdi import HOURGLASS_CURSOR
from wx._gdi import STANDARD_CURSOR
from wx.stc import STC_EOL_CRLF
import  wx.lib.newevent
from zipfile import ZipFile
import zipfile
import JALsPy_globals
import os
import platform
import re
import subprocess
import sys
import time
import wx






class UIManager:
    MY_EVT_CALLBACK = None
    (UpdateCallbackEvent, MY_EVT_CALLBACK) = wx.lib.newevent.NewEvent()

    devices = []
    def __init__(self):
        
        self.debugView= None
        self.editView = None
        self.browserView = None
        
        self.mainSplitter = None
        self.tabEditMaximized = False
        self.tabBrowserMaximized = False
        self.mainEditor = None
        self.browserEditor = None
        self.browserTree = None
        self.browserSplitter = None
        self.outLineTree = None
        self.outLineSearch = None
        self.compileTab = None
        self.listAsm = None
        self.listLang = None
        self.listResult = None
        self.listWatchVars = None
        self.listWatchRegs = None
        self.listWatchDataEEProm = None
        self.listUnitTest = None
        self.listBreakpoint = None
        self.compileLog = None
        self.helpText = None
        self.inOutPanel = None
        self.inOutSizer = None
        
        self.bottomSplitter = None # debug view
        self.topSplitter = None # debug view
        
        
        self.bNextLang = None
        self.bNextAsm = None
        self.varFilter = None
        self.regFilter = None
        self.dataEEPromFilter = None
        self.drawWindow = None
        self.explainAsmText = None
        self.fixedMark = None
        self.deepSearchText = None
        self.deepSearchTree = None
        self.browserSplitter = None
        self.searchInComment = None
        
        
        self.needClose = False
        self.hexFileName = None
        self.statusBar = None
        self.top = None
        self.tab = None
        self.varTypeDict = None
        self.emu = None
        self.threadEngine = None
        self.watchedReg = set()
        self.oldWatchedValues={} # to save watched value so that we can color value that changed
        self.oldWatchedVars = {}
        self.plugins = []
        self.nodesForAddress = [0]*1024*128
        self.devicesForAddressRead = [0]*1024*128
        self.devicesForAddressWrite = [0]*1024*128

        self.picName = ""
        
        for i in range(0,1024*128):
            self.nodesForAddress[i] = None
            self.devicesForAddressRead[i] = None
            self.devicesForAddressWrite[i] = None

        self.running = False
        self.breakpoints = {}
#        self.breakpoints = [0] * 1024*128
#        for i in range(0,1024*128):
#            self.breakpoints[i] = False      
        
   
    def newProject(self):
        self.stop()
        self.top.toolbar.EnableTool(Context.TOOL_RUN,False)
        self.top.GetMenuBar().Enable(124,False)
        
        self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,False)
        
        self.top.toolbar.EnableTool(Context.TOOL_OPEN,True)
        self.top.toolbar.EnableTool(Context.TOOL_NEW,True)
        self.top.GetMenuBar().Enable(100,True)
        self.top.GetMenuBar().Enable(101,True)
        self.top.GetMenuBar().Enable(103,True)
        
        self.varTypeDict = None
        self.running = False
        self.emu = None
        self.watchedReg =set()
        self.oldWatchedValues={} # to save watched value so that we can color value that changed
        self.oldWatchedVars = {}
        self.threadEngine = None
        
        self.breakpoints = {}
        #self.breakpoints = [0] * 1024*128
        #for i in range(0,len( self.breakpoints )):
        #    self.breakpoints[i] = False      
        self.mainEditor.SetText("")
        self.mainEditor.filename=""
        self.hexFileName = None
        self.browserEditor.SetText("")
        self.browserEditor.filename=""
        self.tab.SetPageText(1,"Main file")
        self.tab.SetPageText(2,"Include viewer")
        self.outLineTree.DeleteAllItems()
        self.browserTree.DeleteAllItems()
        self.listAsm.DeleteAllItems()
        self.listLang.DeleteAllItems()
        self.listResult.DeleteAllItems()
        self.listWatchVars.DeleteAllItems()
        self.listWatchRegs.DeleteAllItems()
        self.inOutPanel.DestroyChildren()
        self.compileLog.Clear()
        self.plugins = []
        
    
    def compileProjectAlternate(self):
        self.compileProject(Context.compiler2,Context.libpath2,Context.compiler2Options)
        
    def startProgrammer(self):
        options = Context.programmerOptions
        options = options.replace("%jal",self.mainEditor.filename)
        options = options.replace("%hex",self.mainEditor.filename.replace(".jal",".hex"))
        options = options.replace("%asm",self.mainEditor.filename.replace(".jal",".asm"))
        options = options.replace("%F",self.mainEditor.filename.replace(".jal",""))
        os.system(Context.programmer+" "+options )

    def getPicName(self):
        picName = "16f877a"
        
        search_paths = Context.libpath+";"+os.path.dirname(self.mainEditor.filename)
        files =[self.mainEditor.filename]
        files += list(EditorUtil.findAllIncludesWithPath(self.mainEditor.GetText(),search_paths))

        for filename in files:
           # print "CHECK FILE "+filename
           file = open (filename)
           num = 0
           for lg in file:
              lg = (lg.lstrip()).rstrip()              
              lg.replace( ";","--")				


              p1 = lg.find( "pragma" )
              if p1 >= 0 :
                 p2 = lg.find( "target" )
                 if ( p2 > p1 ):
                    p3 = lg.find( "chip" )
                    if ( p3 > p2 ):                 	
                       p0 = lg.find( "--" )
                       if ( p0 < 0 ) or ( p0 > p3) :
                          lg = lg[ p3 + len("chip"): ]
                          p0 = lg.find( " " )
                          if p0 > 0:
                             lg = lg[:p0]
                          picName = (lg.lstrip()).rstrip()
                          # print "PICNAME  :" + picName + ":"   
           file.close()
        # print "Got Picname " + picName
        self.picName = picName               

   
    def compileProject(self,compiler,libpath,options):
       self.top.SetCursor(HOURGLASS_CURSOR)
       
       options = options.strip()
       if compiler=="":
           compiler = Context.compiler
       if libpath=="":
            libpath = Context.libpath
            
       
       if (self.mainEditor.filename != "") and not self.mainEditor.filename.endswith("*"):
           
           if self.mainEditor.filename.endswith(".txt"):
               #parseRes = AnnotationParser.parse(self.mainEditor.GetText())
               #self.buildInOut(parseRes["inputs"],parseRes["outputs"])
               self.importHex(self.mainEditor.filename.replace(".txt",".hex"))
               self.compileLog.AppendText("I/O Updated")
               return
           
           
           self.listResult.DeleteAllItems()
           self.compileLog.Clear()
           
           #clean indicator
           for i in range(0,self.mainEditor.GetLineCount()):
                   self.mainEditor.unMarkLine(i)
           
           
           # AF look for better solution 
           # need to update FSR regs in format
           self.getPicName()
           self.pic = PicFactory( "pic_" + self.picName )           
           Format.spReg = self.pic.fsr_regs

           parseRes = AnnotationParser.parse(self.mainEditor.GetText())
           anno_options = parseRes["options"]
           vlibpath = None
           if "virtual_delay" in anno_options :
               # these files will shortcut real  files in virtual mode...
               vpath =  os.path.abspath(".")+os.sep+"virtual"
               vlibpath =vpath+";"+libpath
           
           #
           # Start compiler
           #
           arguments = [compiler]
           varguments = [compiler]
           opt = options.split(" ")
           if (opt!= None) and len(opt)>0 and options!= "":
              arguments+=opt
              varguments +=opt
           
           self.hexFileName = self.mainEditor.filename.replace(".jal",".hex")
           virtualHexFileName = self.buildVirtualFileName(self.hexFileName)
           arguments+=["-s",libpath,self.mainEditor.filename]
           
           self.compileLog.AppendText("Compilation line is : ")
           for arg in arguments:
               self.compileLog.AppendText(arg+" ")
           self.compileLog.AppendText("\n")
           if wx.Platform == '__WXMSW__':
               p = subprocess.Popen(args=arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
           else :
               p = subprocess.Popen(args=arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False)
               
           outputlines = p.stdout.readlines()
           p.wait()
           
           
           #
           # handle result
           #
           i = 0
           hasErrors = True
           message = ""
           for lg in outputlines:
                message += lg
                
                if lg.startswith("0 error") :
                    hasErrors = False
                elif ".jal" in lg:
                    try :
                        lg = lg.strip()
                        
                        lineNum =""
                        filename =""
                        msg =""
                        part = 0
                        for c in lg :
                            if c == ':' and len(filename) > 1:
                                part += 1
                            elif part == 0 :
                                filename += c
                            elif part == 1 :
                                lineNum += c
                            if part > 1:
                                msg += c
                        msg = msg[1:]
                        
                        self.listResult.InsertStringItem(i,lineNum )
                        self.listResult.SetStringItem(i,1,  filename)
                        self.listResult.SetStringItem(i,2, msg )
                        
                        if self.mainEditor.filename == filename:
                            try :
                                self.mainEditor.markLineError(int(lineNum)-1) # error is 1 based
                            except : pass
                        elif  self.browserEditor.filename == filename:
                            try :
                                self.browserEditor.markLineError(int(lineNum)-1) # error is 1 based
                            except : pass
                        else:
                            self.listResult.SetItemTextColour(i,"#A0A0A0")    
                        i += 1
                    except : pass
           self.compileLog.AppendText(message)
           
           # clear breakpoints
           self.removeAllBreakpoints()
           
           if (hasErrors):
               self.tab.SetSelection(Context.TAB_EDIT) # goto edit tab
               self.top.GetStatusBar().SetStatusText("Compile status : Errors")
               self.listAsm.DeleteAllItems()
               self.listLang.DeleteAllItems()
               self.compileTab.SetSelection(Context.COMPILE_ERROR_TAB) 
               self.top.toolbar.EnableTool(Context.TOOL_RUN,False)
               self.top.GetMenuBar().Enable(124,False)
               self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,False)


           else:
                #update list, use the pasers...
               self.compileTab.SetSelection(Context.COMPILE_RESULT_TAB)
               self.top.GetStatusBar().SetStatusText("Compile status : Ok")
               
               noDebugList = parseRes["noDebug"] 
               debugList =parseRes["debug"]  
               
               if parseRes["regfilter"] != "":
                   self.regFilter.SetLabel(parseRes["regfilter"])
               if parseRes["varfilter"] != "":
                   self.varFilter.SetLabel(parseRes["varfilter"])
                
               asmFileName = self.mainEditor.filename.replace(".jal",".asm")   
               if "virtual_delay" in anno_options :
                   asmFileName = self.buildVirtualFileName(asmFileName)
                   self.compileLog.AppendText("\nBuilding simulation file : "+virtualHexFileName+"\n")
                   varguments+=["-s",vlibpath,"-asm",asmFileName,"-hex",virtualHexFileName,self.mainEditor.filename]
                   
                   if wx.Platform == '__WXMSW__':
                        p = subprocess.Popen(args=varguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
                   else :
                        p = subprocess.Popen(args=varguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False)

                   outputlines = p.stdout.readlines()
                   p.wait()
                
               self.asmParser = JalV2AsmParser()
               wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
               
               if "virtual_delay" in anno_options :
                   self.buildEmu(virtualHexFileName,wholeCode)
               else :
                   self.buildEmu(self.hexFileName)
               
               self.langParser = JalV2AsmParser()
               code = self.langParser.parseAsmFile(asmFileName, noDebugList,debugList)
               self.loadDebugList(self.emu.instructionList,self.emu.lastAddress,code,wholeCode)
               self.varTypeDict = JalV2AsmParser.buildVarTypeDict(wholeCode)
                              
               #build in / out
               self.buildInOut(parseRes["inputs"],parseRes["outputs"])
               self.devices = parseRes["devices"]
              
               self.buildDevices(self.devices)
               self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
               self.top.GetMenuBar().Enable(124,True)
               self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
               
           self.listUnitTest.DeleteAllItems()           
           self.markWarning(outputlines) # need to be done after loading jalFileName
           
           # to avoid some redraw coloring problems...
           self.mainEditor.Colourise(0,-1)
           self.browserEditor.Colourise(0,-1)
        
       self.top.SetCursor(STANDARD_CURSOR)
           
    
    
    def buildVirtualFileName(self,filename):
        path = os.path.dirname(filename)
        file = os.path.basename(filename)
        return path+os.sep+"~"+file
    
    def programMemCallBack(self,data,adr,lastAddress,instructionList):
        # any nedd to update asm debug list ?
        if adr<= lastAddress:
           self.asmParser = JalV2AsmParser()
           asmFileName = self.mainEditor.filename.replace(".jal",".asm")
           wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
           self.loadDebugList(instructionList,lastAddress,None,wholeCode)            
    
    def buildEmu(self,hexFileName,wholeCode=None):
        adrDelay = None
        if wholeCode != None :
            jalCode = [""]*1024*128
            adrDelay = {}
            # build an array with address as index and code as content
            for i in range (0, len (wholeCode)) :
                adr = str(wholeCode[i].address).strip()
                if adr != "" :
                    if jalCode[int(adr)] != "":
                        jalCode[int(adr)] += str("-"+wholeCode[i].line)
                    else :
                        jalCode[int(adr)] = str(wholeCode[i].line)
            
            for i in range (0, len (jalCode)) :
                line = jalCode[i].replace("--",";")
                line = line.split(";")[0]
                line = line.upper().strip()
                if "DELAY_" in line and "PROCEDURE" not in line.upper():
                    line = line[line.index("DELAY_"):]
                    # print line
                    factor =1
                    if "MS" in line :
                        factor = 0.001
                    elif "US" in line :
                        factor = 0.000001
                    
                    time=0
                    nbr = 1
                    partNbr = line.split("(")
                    if len(partNbr) > 1:
                        nbr = partNbr[1]
                        try :
                            nbr = int(nbr.replace(")","").strip())
                        except : nbr = 1
                    time = line[6:]
                    time = re.split("[MSU]+",time)[0]
                    delay = int(time) * nbr * factor
                    adrDelay[i]= delay        
                    # print " adrDelay[i] %d " % i + " = %d " % delay
        
        self.emu = PicEngine.newInstance( self.picName , hexFileName, self.programMemCallBack, adrDelay)
        mon = RegisterUpdater(self.watchedReg)
        devTarget =  DeviceTargetStateMonitor(self) # use to update device state from emu.state (ie led.. lcd...)
        devSource =  DeviceSourceStateMonitor(self) # used to update emu.state from device state (ie buttons)
        
        #profiler = ProfilerPulgin(self)
        #self.plugins = [profiler]     
        #self.emu.monitors = [profiler]     
        
        self.emu.state.globalWriteMonitors = [mon,devTarget]  
        self.emu.state.globalReadMonitors = [devSource] 
    
    def buildDevices(self,devices):
        if devices != None :
            nodeCounter = 0
            dc =wx.ClientDC ( self.drawWindow )
            self.drawWindow.diagram.Clear(dc)
            self.drawWindow.diagram.RemoveAllShapes()
           
            for i in range(0,1024*128):
                self.nodesForAddress[i] = None
                self.devicesForAddressRead[i] = None
                self.devicesForAddressWrite[i] = None
                
            for device in devices :
                parts = device.split(" ")
                deviceFullName = parts[1]
                deviceModule = deviceFullName.split(".")[0]
                deviceClass = deviceFullName.split(".")[1]
                deviceArgs = parts[2:]
                print sys.path
                exec("from %s import %s" % (deviceModule,deviceClass))
                
                deviceInstance = eval("%s()" % deviceClass)
                deviceInstance.NodeNr = [0] * (len(deviceArgs)+1)
                
                cptDeviceInstanceNodes = 1 # JALsPy defined that pin start at 1
                for arg in deviceArgs:
                    # transfer arg to device instance
                   
                    if "=" in arg :
                        parts = arg.split("=")
                        cmd = "deviceInstance.%s = %s" % (parts[0],parts[1])
                        exec(cmd)
                        
                    elif arg.startswith("pin_") :
                        pin = arg.upper()
                        #convert pin_a0 -> 5 bit 1
                        port = ord(pin[4])-60 
                        bit = pow(2,(ord(pin[5])-48))
                        
                        # some JALsPy needs...
                        JALsPy_globals.V_Node.append(1)
                        JALsPy_globals.G_Node.append(1)
                        JALsPy_globals.C_Node.append(1)
                        JALsPy_globals.T_Node.append(1)
                        deviceInstance.NodeNr[cptDeviceInstanceNodes] = nodeCounter
                        
                        # build a static map of (node - address_bit) for an address
                        # useful to update the NodeList (JALsPy_globals.V_Node) on which the device relies
                        # to know their states
                        nodesAndBits = self.nodesForAddress[port]
                        if (nodesAndBits == None) :
                            nodesAndBits = []
                        nodesAndBits.append((nodeCounter,bit)) # (6,128) -> node 0 is on portb bit 7 
                        self.nodesForAddress[port] = nodesAndBits   # [addr] = [(nodex,addr_bit),(nodey,addr_bit),...]
                        
                        # build a static map to retrieves all devices for an address
                        # useful to know wich devices need to be updated when a register changes
                        # comp needs update only if pic_pin  is output
                        #if self.emu.state.isOutput(port,bit): 
                        devicesForAddr = self.devicesForAddressWrite[port]
                        if (devicesForAddr == None) :
                            devicesForAddr = set()
                        devicesForAddr.add(deviceInstance)
                        self.devicesForAddressWrite[port] = devicesForAddr
                        print "device "+str(deviceInstance.__class__)+" binded to "+arg+" as target, node="+str(nodeCounter)
                        
                        #else :
                            #inputs
                        devicesForAddr = self.devicesForAddressRead[port]
                        if (devicesForAddr == None) :
                            devicesForAddr = set()
                        devicesForAddr.add(deviceInstance)
                        self.devicesForAddressRead[port] = devicesForAddr
                        print "device "+str(deviceInstance.__class__)+" binded to "+arg+" as source, node="+str(nodeCounter)
                        #end
                        
                        
                        cptDeviceInstanceNodes+=1
                        nodeCounter += 1
                        
                    elif arg.upper() == "LOW" or arg.upper() == "OFF" or arg.upper() == "FALSE":
                         print "device "+str(deviceInstance.__class__)+" connected to low, node="+str(nodeCounter)

                         deviceInstance.NodeNr[cptDeviceInstanceNodes] = nodeCounter
                         JALsPy_globals.V_Node.append(1)
                         JALsPy_globals.G_Node.append(1)
                         JALsPy_globals.C_Node.append(1)
                         JALsPy_globals.T_Node.append(1)
                         
                         JALsPy_globals.V_Node[nodeCounter] = 0 # 0 Volt
                         cptDeviceInstanceNodes+=1
                         nodeCounter += 1
                        
                        
                    elif arg.upper() == "HIGH" or arg.upper() == "ON" or arg.upper() == "TRUE":
                         print "device "+str(deviceInstance.__class__)+" connected to high, node="+str(nodeCounter)

                         deviceInstance.NodeNr[cptDeviceInstanceNodes] = nodeCounter
                         JALsPy_globals.V_Node.append(1)
                         JALsPy_globals.G_Node.append(1)
                         JALsPy_globals.C_Node.append(1)
                         JALsPy_globals.T_Node.append(1)
                         
                         JALsPy_globals.V_Node[nodeCounter] = 5 # 5 Volt
                         cptDeviceInstanceNodes+=1
                         nodeCounter += 1
                    
                deviceInstance.init()
                shape = deviceInstance.shape
                shape.SetX(deviceInstance.x)
                shape.SetY(deviceInstance.y)
                self.drawWindow.diagram.AddShape(shape)
                shape.Show(True)
                self.drawWindow.diagram.Redraw(dc)

                
            
        
    def buildInOut(self,inputs,outputs):
        self.inOutPanel.DestroyChildren()
        li = len(inputs)
        lo = len(outputs)
        max = li
        if lo>li :
            max = lo
        for i in range(0,max):
            if i< li:
                input = inputs[i]
                butHandler = None
                if ((hasattr(input, "type")) and (input.type == "labelIn")):
                    comp = wx.StaticText(self.inOutPanel, -1,input.name)
                    self.inOutSizer.Add(comp)
                    
                if (input.type == "mpu"):
                    but = wx.Button(self.inOutPanel, -1, input.name)
                    butHandler = MpuHandler(self.callbackRead,self.callbackWrite)
                    but.SetToolTipString(input.pin)
                    but.Bind(wx.EVT_LEFT_DOWN, butHandler.OnClickDown)
                    but.Bind(wx.EVT_LEFT_UP, butHandler.OnClickUp)
                    self.inOutSizer.Add(but)
                elif (input.type == "mpd"):
                    but = wx.Button(self.inOutPanel, -1, input.name)
                    butHandler = MpdHandler(self.callbackRead,self.callbackWrite,input.pin)
                    but.SetToolTipString(input.pin)
                    but.Bind(wx.EVT_LEFT_DOWN, butHandler.OnClickDown)
                    but.Bind(wx.EVT_LEFT_UP, butHandler.OnClickUp)
                    self.inOutSizer.Add(but)
                elif (input.type == "ppu"):
                    but = wx.CheckBox(self.inOutPanel, -1, input.name)
                    butHandler = PpuHandler(self.callbackRead,self.callbackWrite)
                    but.SetToolTipString(input.pin)
                    but.Bind(wx.EVT_CHECKBOX, butHandler.OnClickDown)
                    #but.Bind(wx.EVT_LEFT_UP, butHandler.OnClickUp)
                    self.inOutSizer.Add(but)
                elif (input.type == "ppd"):
                    but = wx.CheckBox(self.inOutPanel, -1, input.name)
                    butHandler = PpdHandler(self.callbackRead,self.callbackWrite,input.pin)
                    but.SetToolTipString(input.pin)
                    but.Bind(wx.EVT_CHECKBOX, butHandler.OnClickDown)
                    #but.Bind(wx.EVT_LEFT_UP, butHandler.OnClickUp)
                    self.inOutSizer.Add(but)
                elif (input.type == "pot"):
                    # 0..1023 -> 10 bit ADC 
                    
                    self.buildNamedSliderComp(self.inOutSizer, input.name, input.pin)
                    
                elif (input.type=="midiSender") or (input.type=="asciiSender") or (input.type=="byteSender") :
                    but = input.buildUI(self.inOutPanel,self.callbackRead,self.callbackWrite)
                    self.emu.state.uartProvider = input
                    self.inOutSizer.Add(but)
                
            else:
                self.inOutSizer.Add(wx.StaticText(self.inOutPanel,-1,""))
            if i< lo:
                output = outputs[i]
                comp = None
                if ((hasattr(output, "type")) and (output.type == "labelOut")):
                    comp = wx.StaticText(self.inOutPanel, -1,output.name)
                    self.inOutSizer.Add(comp)
                    
                elif isinstance(output, watchInfo):
                    if output.type in("dec","bin","hex"):
                        ui = self.buildNamedTextUI(self.inOutSizer, output.name)
                        if hasattr(self, "langParser"):
                            comp = Watch(ui,output.address,output.type,self.langParser.varAdrMapping)
                        else :
                            comp = Watch(ui,output.address,output.type)
                        
                    elif output.type == "lcd":
                        uiLcd = wx.TextCtrl(self.inOutPanel,size=(12*int(output.args[0]), 90),style=wx.TE_MULTILINE)
                        uiLcd.SetBackgroundColour("black")
                        uiLcd.SetForegroundColour("#40C040")
                        uiLcd.SetFont(wx.Font(10, wx.MODERN, wx.NORMAL, wx.BOLD))
                        self.inOutSizer.Add(uiLcd)
                        comp = LCD(uiLcd,output.address,output.args[0])

                elif isinstance(output, Dual7Seg) :
                    ui = self.buildNamedLedUI(self.inOutSizer, output.name)
                    output.ui = ui
                    comp = output
                    
                elif isinstance(output, LED) :
                    ui = self.buildNamedTextUI(self.inOutSizer, output.name)
                    if hasattr(self, "langParser"):
                        comp = LED(ui,output.address,output.bit,self.langParser.varAdrMapping)
                    else :
                        comp = LED(ui,output.address,output.bit)
                
                
                elif isinstance(output, CLED) :
                    gray =  wx.Image(FileUtil.opj('icons/gray.GIF'), wx.BITMAP_TYPE_GIF).ConvertToBitmap()
                    ui = self.buildNamedLedOffUI(self.inOutSizer, output.name,gray)
                    col = output.color
                    if col == "red" :
                        on =  wx.Image(FileUtil.opj('icons/red.GIF'), wx.BITMAP_TYPE_GIF).ConvertToBitmap()
                    elif col == "blue" :
                        on =  wx.Image(FileUtil.opj('icons/blue.GIF'), wx.BITMAP_TYPE_GIF).ConvertToBitmap()
                    elif col == "green" :
                        on =  wx.Image(FileUtil.opj('icons/green.GIF'), wx.BITMAP_TYPE_GIF).ConvertToBitmap()
                    elif col == "orange" :
                        on =  wx.Image(FileUtil.opj('icons/orange.GIF'), wx.BITMAP_TYPE_GIF).ConvertToBitmap()
                    elif col == "yellow" :
                        on =  wx.Image(FileUtil.opj('icons/yellow.GIF'), wx.BITMAP_TYPE_GIF).ConvertToBitmap()

                    if hasattr(self, "langParser"):
                        comp = CLED(ui,gray,on,output.address,output.bit,output.color,self.langParser.varAdrMapping)
                    else :
                        comp = CLED(ui,gray,on,output.address,output.bit,output.color)
                
                elif isinstance(output, UpDownCounter):
                    ui = self.buildNamedTextUI(self.inOutSizer, output.name)
                    output.ui = ui
                    comp = output
                    
                elif (output.type=="uartReceiver"):
                    ui = output.buildUI(self.inOutPanel,self.callbackRead,self.callbackWrite)
                    self.inOutSizer.Add(ui)
                    self.emu.state.uartReceiver = output
                    comp = output
                
                if comp != None and hasattr(comp, "address"):                           
                     self.emu.state.appendMonitor( comp )
            else:
                self.inOutSizer.Add(wx.StaticText(self.inOutPanel,-1,""))
        
        #hack due to redraw problems on windows   
        self.bottomSplitter.SetSashPosition(self.bottomSplitter.GetSashPosition()+1,True) 
        self.bottomSplitter.SetSashPosition(self.bottomSplitter.GetSashPosition()-1,True) 

    #
    # Used by button's handler (in module picshell.ui.debug.comp.ButtonHandler
    #
    def callbackRead(self,port):
        return self.emu.state.absreg(port)
    #
    # Used by button's handler (in module picshell.ui.debug.comp.ButtonHandler
    #
    def callbackWrite(self,port,value):
        self.emu.state.abswrite(port,value)
        

    def callbackWriteAdc(self,pinNumber,value):
        # print "UPDATE ADC FROM UI channel: %d" % int( pinNumber ) + " to value %d" % value        
        self.emu.state.adc[int(pinNumber)] = value
    
    def buildNamedTextUI(self,psizer,name):
        panel = wx.Panel(self.inOutPanel,-1)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        panel.SetSizer(sizer)
        label = wx.StaticText(panel,-1," "+name)
        ui = wx.TextCtrl(panel)
        ui.SetFont(wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL))
        sizer.Add(ui,0,0)
        sizer.Add(label,0,0)
        psizer.Add(panel,0,0)
        return ui  
    
    def buildNamedSliderComp(self,psizer,name,pin):
        panel = wx.Panel(self.inOutPanel,-1)
        
        slider =wx.Slider(panel, -1, 0, 0, 1023, wx.DefaultPosition, (250, -1),
                       wx.SL_HORIZONTAL | wx.SL_LABELS)
        butHandler = PotHandler(self.callbackWriteAdc,pin)
        slider.SetToolTipString(pin)
        slider.Bind(wx.EVT_SCROLL,butHandler.OnChange)
        
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        panel.SetSizer(sizer)
        label = wx.StaticText(panel,-1," "+name)
        sizer.Add(slider,0,0)
        sizer.Add(label,0,0)
        psizer.Add(panel,0,0)
        
    
    def buildNamedLedUI(self,psizer,name):
        panel = wx.Panel(self.inOutPanel,-1)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        panel.SetSizer(sizer)
        label = wx.StaticText(panel,-1," "+name)
        #ui = wx.TextCtrl(panel)
        #ui.SetFont(wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL))
        
        ui = gizmos.LEDNumberCtrl(panel, -1, (25,25), (280, 50))
        
        sizer.Add(ui,0,0)
        sizer.Add(label,0,0)
        psizer.Add(panel,0,0)
        return ui 
    
    def buildNamedLedOffUI(self,psizer,name,gray):
        panel = wx.Panel(self.inOutPanel,-1)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        panel.SetSizer(sizer)
        label = wx.StaticText(panel,-1," "+name)
        ui = wx.StaticBitmap(panel, -1, gray, (10, 0), (gray.GetWidth(), gray.GetHeight()))
        sizer.Add(ui,0,0)
        sizer.Add(label,0,0)
        psizer.Add(panel,0,0)
        return ui      
    
    def reset(self):
        if self.running:
            self.stop() # reset will be call at the and of callback
            self.running = False
            self._reset()
        else:
            self._reset()
            
    def close(self,event): 
        app = Context.top
        Context.APP_SIZE_X = app.GetSize()[0]
        Context.APP_SIZE_Y = app.GetSize()[1]
        Context.APP_POS_X = app.GetPosition()[0]
        Context.APP_POS_Y = app.GetPosition()[1]
        Context.FONTSIZE += self.mainEditor.GetZoom()
        Context.BROWSER_SASH_POSITION = self.browserSplitter.GetSashPosition(0)
        Context.save()
                
        if self.running:
            self.needClose = True
            self.stop() # reset will be call at the and of callback
            time.sleep(1)
            sys.exit(0)
            event.Skip()
        else:
            sys.exit(0)
            event.Skip()
      
    
           
    def markWarning(self,outputlines):
        for lg in outputlines:
            if ".jal" in lg:
               
                try :
                    parts = lg.split(":") 
                    if self.mainEditor.filename == parts[0]+":"+parts[1]:
                        try :
                            if " warning:" in lg:   
                                self.mainEditor.markLineWarning(int(parts[2])-1) # error is 1 based
                        except : pass
                    elif  self.browserEditor.filename == parts[0]+":"+parts[1]:
                        try :
                            if " warning:" in lg:
                                self.browserEditor.markLineWarning(int(parts[2])-1) # error is 1 based
                        except : pass
                except : pass
    def OnErrorListDCLICK(self,event):
        filename = self.listResult.GetItem(self.listResult.GetFirstSelected(),1)
        filename = filename.GetText().strip()

        if ( filename == self.mainEditor.filename ) :
           self.tab.SetSelection( Context.TAB_EDIT )
        else:
           self.openEditor(Context.TAB_BROWSER, filename)
           self.tab.SetSelection( Context.TAB_BROWSER )
           
        self.OnErrorList(event)
            
    def OnErrorList(self,event):
        lg = self.listResult.GetItem(self.listResult.GetFirstSelected(),0)
        lg = lg.GetText().strip()
        filename = self.listResult.GetItem(self.listResult.GetFirstSelected(),1)
        filename = filename.GetText().strip()
        if (lg != ""):
            if (self.mainEditor.filename == filename):
                self.tab.SetSelection(Context.TAB_EDIT)
                self.mainEditor.GotoLine(int(lg)-1)
                self.mainEditor.SetCurrentPos(self.mainEditor.GetLineEndPosition(int(lg)-1))
                self.mainEditor.SetFocus()
            
            elif self.browserEditor.filename == filename:
                self.tab.SetSelection(Context.TAB_BROWSER)
                self.browserEditor.GotoLine(int(lg)-1)
                self.browserEditor.SetCurrentPos(self.browserEditor.GetLineEndPosition(int(lg)-1))
                self.browserEditor.SetFocus()
    
    #----------------------------------------------------------------
    # Browser
    #
    def updateBrowserTree(self):
        self.browserTree.DeleteAllItems()
        root = self.browserTree.AddRoot('Root')
        includes = self.browserTree.AppendItem(root, 'includes')
        self.browserTree.SetItemBold(includes,True)
        pathes = Context.libpath+";"+os.path.dirname(self.mainEditor.filename)
        allincludes = EditorUtil.findAllIncludedFiles(self.mainEditor.GetText(),pathes)
        self.methodesMapping = {}
        for inc in allincludes:
            item = self.browserTree.AppendItem(includes, inc)
            self.browserTree.SetItemBold(item,True)
            funcRes = EditorUtil.findInFileStartswithNoPath(inc,"function",1)
            libFunc = funcRes[0]
            libFuncMapping = funcRes[1]

            procRes = EditorUtil.findInFileStartswithNoPath(inc,"procedure",1)
            libProc = procRes[0]
            libProcMapping = procRes[1]
            
            methodes = set(libFunc+libProc)
            self.methodesMapping.update(libFuncMapping)
            self.methodesMapping.update(libProcMapping)

            for func in methodes:
                self.browserTree.AppendItem(item,func)
        self.browserTree.Expand(includes)    

    def CheckBrowserModified( self,parentItem ):
        openFile = False
    
        # AF Check if there are any modified files, if so, show dialog box   
        if ( self.browserEditor.parentTab.GetPageText(Context.TAB_BROWSER).endswith("*") ):

	        dlg = wx.MessageDialog(None, 'Modified file, do you really want to open another file...\n'+
	        'Select cancel to abort exit,\n' +
	        'yes to save the files,\n' +
	        'no to open a new file without saving the modified files',
	          'Open new file, with modified files', wx.CANCEL  | wx.YES_NO | wx.ICON_EXCLAMATION)
	        dlgResult = dlg.ShowModal()
	        dlg.Destroy()

	        if ( dlgResult == wx.ID_YES ) :
	           self.saveEditor(Context.TAB_EDIT)
	           openFile = True
	        elif ( dlgResult == wx.ID_NO ) :
	           openFile = True
        else:
           openFile = True
        return openFile
    
    def OnBrowserTreeSelChanged(self, event):
        try :
            item =  event.GetItem()
            itemText = self.browserTree.GetItemText(item)
            parentItem = self.browserTree.GetItemParent(item)
            parentText =  self.browserTree.GetItemText(parentItem)
            if self.CheckBrowserModified(parentItem):
            #if not ( self.browserEditor.parentTab.GetPageText(Context.TAB_BROWSER).endswith("*") ):
                if itemText in self.methodesMapping:
                    if self.browserEditor.filename != parentText:
                        self.openEditor(2,filename=parentText)
                    line = -1
                    line = EditorUtil.findLineForMethod(self.browserEditor.GetText(),itemText)
                    if line >-1:
                        self.browserEditor.GotoLine(line)
                        self.browserEditor.SetSelectionStart(self.browserEditor.GetLineEndPosition(line)- len(self.browserEditor.GetLine(line))+2)
                        self.browserEditor.SetSelectionEnd(self.browserEditor.GetLineEndPosition(line))                
                else:
                    self.openEditor(2,filename=itemText)
            else:
                self.GetStatusBar().SetStatusText("Can't show this file because the current one hasn't been saved")
        except : pass # not realy clean handling for now...        

    def _reset(self):
        self.top.SetCursor(HOURGLASS_CURSOR)
        
        #
        # Realy dirty need to be cleaned !
        #
        self.clearDebugListSelectedLine()
        self.buildDevices(self.devices)
        self.watchedReg =set()
        self.oldWatchedValues={} # to save watched value so that we can color value that changed
        self.oldWatchedVars = {}
        self.listWatchVars.DeleteAllItems()
        self.listWatchRegs.DeleteAllItems()
        self.listWatchDataEEProm.DeleteAllItems()
        
        for plugin in self.plugins:
            plugin.reset()        
            
        uartProvider = None
        uartReceiver = None
        # get a thread engine
        if self.emu != None:
            if hasattr(self.emu.state, "uartProvider"):
                uartProvider = self.emu.state.uartProvider
            if hasattr(self.emu.state, "uartReceiver"):
                uartReceiver = self.emu.state.uartReceiver
            
            if hasattr(self.emu.state, "monitors"):
                monitors = self.emu.state.monitors
                for mon in monitors:
                    mon.reset()
                    
            
            hexFileName = self.emu.hexfilename

            parseRes = AnnotationParser.parse(self.mainEditor.GetText())
            self.buildEmu(hexFileName)

            self.emu.state.monitors = monitors
            
            if uartProvider != None :
                self.emu.state.uartProvider = uartProvider
            if uartReceiver != None :
                self.emu.state.uartReceiver = uartReceiver
            
            # Update asm list as it may have been update by program eeprom change
            self.asmParser = JalV2AsmParser()
            asmFileName = self.mainEditor.filename.replace(".jal",".asm")
            parse_an = parseRes["options"]
            
            if "virtual_delay" in parse_an :
                asmFileName = self.buildVirtualFileName(asmFileName)
           
            if os.path.exists(asmFileName):
                wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
                self.loadDebugList(self.emu.instructionList, self.emu.lastAddress, None, wholeCode)
                
            
            noDebugList = parseRes["noDebug"] 
            debugList =parseRes["debug"]  
           
            if parseRes["regfilter"] != "":
               self.regFilter.SetLabel(parseRes["regfilter"])
            if parseRes["varfilter"] != "":
               self.varFilter.SetLabel(parseRes["varfilter"])
               
            self.hexFileName = self.mainEditor.filename.replace(".jal",".hex")
            virtualHexFileName = self.buildVirtualFileName(self.hexFileName)
            self.asmParser = JalV2AsmParser()
            wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
            if "virtual_delay" in parse_an :
                self.buildEmu(virtualHexFileName,wholeCode)
            else :
                self.buildEmu(hexFileName)
           
            self.langParser = JalV2AsmParser()
            code = self.langParser.parseAsmFile(asmFileName, noDebugList,debugList)
            self.loadDebugList(self.emu.instructionList,self.emu.lastAddress,code,wholeCode)
            self.varTypeDict = JalV2AsmParser.buildVarTypeDict(wholeCode)
           
            wx.Yield()
            self.buildInOut(parseRes["inputs"],parseRes["outputs"])
            
            #build in / out
            
            self.devices = parseRes["devices"]
          
            self.buildDevices(self.devices)
            self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
            self.top.GetMenuBar().Enable(124,True)
            self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
        
            self.updateBreakPoints()
        
            self.statusBar.SetStatusText("Reseted")
        self.top.SetCursor(STANDARD_CURSOR)        
    #----------------------------------------------------------------
    # Editor
    #

    # Update editor
    # content : an array of lines
    def updateEditor(self,whichEditor,lines):
        if (whichEditor == 0) or (whichEditor == 1): 
            editor = self.mainEditor
        else :
            editor = self.browserEditor
        content =""
        for line in lines:
            content += line
        editor.SetText(content)

    def getEditor(self,whichEditor):
        if (whichEditor == 2) : 
            editor = self.browserEditor
        else :
            editor = self.mainEditor
        return editor

    # Which editor is the curent Tab
    def saveEditor(self,whichEditor):
        self.top.SetCursor(HOURGLASS_CURSOR)
        editor = self.getEditor(whichEditor)
        filename =  FileUtil.saveEditor(editor.filename,editor)
        if filename!="":
            editor.filename = filename
        self.top.SetCursor(STANDARD_CURSOR)
            
        return filename
    
    def saveEditorAs(self,whichEditor):
        self.top.SetCursor(HOURGLASS_CURSOR)
        editor = self.getEditor(whichEditor)
        filename =  FileUtil.saveEditor("",editor)
        if filename!="":
            editor.filename = filename
        self.top.SetCursor(STANDARD_CURSOR)
        return filename
    
    def openEditor(self,whichEditor,filename="",newProject=False):
        editor = self.getEditor(whichEditor)
        if filename=="":
            filename = FileUtil.open()
        if filename != "":
            if newProject:
                self.newProject()  
            editor.filename = filename
            #editor.SetText(FileUtil.getContentAsText(filename))
            editor.LoadFile(filename)
            editor.ConvertEOLs(STC_EOL_CRLF)
            self.tab.SetPageText(whichEditor,filename)
                    
        if (whichEditor!=Context.TAB_BROWSER):
            self.updateOutLineTree()
            self.updateBrowserTree()
            
        return filename
    
    
    def updateDeepSearchTree(self,match,lib):
        self.deepSearchTree.DeleteAllItems()
        if match != "" :
            allpathes = os.path.dirname(self.mainEditor.filename)+";"+Context.libpath
            match = match.strip()
            #libs = EditorUtil.findAllLibsWithPath(allpathes)
            if self.mainEditor.filename != "" :
                files =[self.mainEditor.filename]
            else:
                files = []
            if lib :
                files += EditorUtil.findAllLibsWithPath(allpathes)
            else :
                files += list(EditorUtil.findAllIncludesWithPath(self.mainEditor.GetText(),allpathes))
            
            root = self.deepSearchTree.AddRoot('Root')
            for filename in files:
                fileRoot = None
                file = open (filename)
                num = 0
                for lg in file:
                    
                    #include comment ?
                    if not self.searchInComment.IsChecked() :
                        lg = lg.replace("--",";")
                        lg = lg.split(";")[0]
                    
                    num +=1
                    found = True
                    for m in match.split(" "):
                        if m.upper() not in lg.upper() :
                            found = False
                            break
                    
                    if found :
                        if fileRoot == None :
                            fileRoot = self.deepSearchTree.AppendItem(root,  filename)
                            self.deepSearchTree.SetItemBold(fileRoot,True)
                        self.deepSearchTree.AppendItem(fileRoot,  str(num)+":"+lg.strip())
                    if fileRoot != None :
                        self.deepSearchTree.Expand(fileRoot)
                        
                file.close()
    
    def OnDeepSearchTreeSelChanged(self, event):
        try :
            item =  event.GetItem()
            itemText = self.deepSearchTree.GetItemText(item)
            parentItem = self.deepSearchTree.GetItemParent(item)
            parentText =  self.deepSearchTree.GetItemText(parentItem)
            editor = None
            if self.mainEditor.filename == parentText :
                editor = self.mainEditor
                self.tab.SetSelection(Context.TAB_EDIT)
            else :
                self.tab.SetSelection(Context.TAB_BROWSER)
                if not self.browserEditor.filename.endswith("*"):
                    editor = self.browserEditor
                    self.openEditor(2,filename=parentText)
            if editor != None :
                line = -1
                line = int(itemText.split(":")[0])-1
                if line >-1:
                    editor.GotoLine(line)
                    editor.SetSelectionStart(editor.GetLineEndPosition(line)- len(editor.GetLine(line))+2)
                    editor.SetSelectionEnd(editor.GetLineEndPosition(line))                
        except : pass
    
    #----------------------------------------------------------------
    # OutLine Tree
    #
    
    # Update the outline tree
    # lines : content of the main editor as an array of lines
    def updateOutLineTree(self,match=""):
        self.clearOutLineTree()
        root = self.outLineTree.AddRoot('Root')
        varRoot = self.outLineTree.AppendItem(root,  'Global')
        funcRoot = self.outLineTree.AppendItem(root, 'Functions')
        procRoot = self.outLineTree.AppendItem(root, 'Procedures')
        annotationRoot = self.outLineTree.AppendItem(root, 'Annotations')
        
        self.outLineTree.SetItemBold(funcRoot,True)
        self.outLineTree.SetItemBold(procRoot,True)
        self.outLineTree.SetItemBold(varRoot,True)
        self.outLineTree.SetItemBold(annotationRoot,True)
        
        self.outLineTree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnOutlineTreeSelChanged, id=1)
        lines = self.mainEditor.GetText().split("\n")
        (funcs,procs,vars) = JalV2Parser.parse(lines)

        
        
        for f in funcs:
            parentAdded = False
            if match == "" or match.upper() in f.upper():
                item = self.outLineTree.AppendItem(funcRoot, f)
                parentAdded = True
            for v in funcs[f]:
                if match == "" or match.upper() in v.name.upper():
                    if not parentAdded:
                        item = self.outLineTree.AppendItem(funcRoot, f)
                        parentAdded = True    
                    self.outLineTree.AppendItem(item, v.type+" "+v.name)
                    if match != "":
                        self.outLineTree.Expand(item)
        for p in procs:
            parentAdded = False
            if match == "" or match.upper() in p.upper():
                item = self.outLineTree.AppendItem(procRoot, p)
                parentAdded = True
            for v in procs[p]:
                if match == "" or match.upper() in v.name.upper():
                    if not parentAdded:
                        item = self.outLineTree.AppendItem(procRoot, p)
                        parentAdded = True    
                    self.outLineTree.AppendItem(item, v.type+" "+v.name)
                    if match != "":
                        self.outLineTree.Expand(item)
        for v in vars:
            if match == "" or match.upper() in v.name.upper():
                self.outLineTree.AppendItem(varRoot, v.type+" "+v.name)
                
        annotations = AnnotationParser.findAnnotations(self.mainEditor.GetText())
        for a in annotations:
            if match == "" or match.upper() in a.upper():
                self.outLineTree.AppendItem(annotationRoot, a)       

        self.outLineTree.Expand(funcRoot)
        self.outLineTree.Expand(procRoot)
        self.outLineTree.Expand(varRoot)
        self.outLineTree.Expand(annotationRoot)
    
    def clearOutLineTree(self):
        self.outLineTree.DeleteAllItems()

    def OnOutlineTreeSelChanged(self,event):
        try:
            item =  event.GetItem()
            itemText = self.outLineTree.GetItemText(item)        
            parentItem = self.outLineTree.GetItemParent(item)
            line = -1
            
            parentText =  self.outLineTree.GetItemText(parentItem)
            if "Functions" == parentText:
                line = EditorUtil.findLineForFunc(self.mainEditor.GetText(),itemText)
            elif "Procedures" == parentText:
                line = EditorUtil.findLineForProc(self.mainEditor.GetText(),itemText)
            elif "Global" == parentText:
                line = EditorUtil.findLineForVar(self.mainEditor.GetText(),itemText)
            elif "Annotations" == parentText:
                line = EditorUtil.findLineForAnnotation(self.mainEditor.GetText(),itemText)
            
            else:
                line = EditorUtil.findLineForVar(self.mainEditor.GetText(),itemText,parentText)       
            if line >-1:
                self.mainEditor.GotoLine(line)
                self.mainEditor.SetSelectionStart(self.mainEditor.GetLineEndPosition(line)- len(self.mainEditor.GetLine(line))+2)
                self.mainEditor.SetSelectionEnd(self.mainEditor.GetLineEndPosition(line))
        except : pass


    def OnDeepSearchIncludes(self,event):
        what = self.deepSearchText.GetValue() 
        self.updateDeepSearchTree(what,False)
    def OnDeepSearchLibs(self,event):
        what = self.deepSearchText.GetValue() 
        self.updateDeepSearchTree(what,True)

    def OnOutlineSearch(self,event):
        key = event.GetKeyCode()
        if key == 319 or key == 13:
            self.outLineTree.SetFocus()
        what = self.outLineSearch.GetValue() 
        self.updateOutLineTree(what)
    
    
    #-------------------------------------------------------------------------------
    # Next action
    # 
    def nextAsm(self):
        self.top.SetCursor(HOURGLASS_CURSOR)
        if (not self.running) and self.listAsm.GetItemCount()>0:
           if (self.threadEngine != None):
                self.threadEngine.stop()
           self.tab.SetSelection(Context.TAB_DEBUG) # goto debug tab
           adr = self.emu.runNext()
           inst = self.emu.getCurInst() 
           self.explainAsmText.SetLabel("")
           self.explainAsmText.AppendText( AsmDocHelp.getAsmDescriptionHelp(inst, self.emu.state))
           self.explainAsmText.AppendText( AsmDocHelp.getAsmBeforeExecutionHelp(inst, self.emu.state))
           self.callback(adr)
           self.explainAsmText.AppendText( AsmDocHelp.getAsmAfterExecutionHelp(inst, self.emu.state))
        self.top.SetCursor(STANDARD_CURSOR)
    
    def nextLang(self):
        self.top.SetCursor(HOURGLASS_CURSOR)
        if (not self.running) and self.listAsm.GetItemCount()>0:
           if hasattr(self, "allLineAddresses"): # inactif si import hex
               addresses = dict( self.allLineAddresses )

               # include asm breakpoint(s)
               for bp in self.breakpoints:
                  addresses[bp] = True 
               #print "ADDRESSES incl BP"
               #print addresses
               self._runTo(addresses ,self.unitTestCallBack)
        self.top.SetCursor(STANDARD_CURSOR)
    # not fully woking for now...    
    def nextStepOverLang(self):
        text =  self.listAsm.GetItem(self.emu.state.pc,Context.COL_COM).GetText()
        print text,
        if not JalV2Parser.mustStepOver(text):
            self.nextLang()
            return    
        
        self.top.SetCursor(HOURGLASS_CURSOR)
        if (not self.running) and self.listAsm.GetItemCount()>0:
            addresses =  [0]*1024*128
            for i in range (0,len( addresses )):
                addresses[i] = False
           
            for a in self.langParser.lineToAdr :
                if (a != None) and (int(a) > self.emu.state.pc) :
                    addresses[a] = True
                    break
            
            # include breakpoint
            for adr,hasBreakpoint in enumerate(self.breakpoints):
                if hasBreakpoint :
                      addresses[adr] = True 
            self._runTo(addresses,self.unitTestCallBack)
        self.top.SetCursor(STANDARD_CURSOR)
           
    def stop(self):
       
       if (self.threadEngine != None):
          self.threadEngine.stop()
          
          #while self.threadEngine.stopped == False : pass
       self.statusBar.SetStatusText("Stopped")  

    def run(self):
         if (not self.running) and self.listAsm.GetItemCount()>0:
            self._runTo(self.breakpoints)
            
    def runUnitTest(self):
        if (not self.running) and self.listAsm.GetItemCount()>0:
             if self.emu != None :
                 self.listUnitTest.DeleteAllItems()
                 lastAddressArray = {}
                 if self.picName.startswith( "18f" ):
                    # AF CHECK TODO FIXME
                    print "SET LAST ADDRESS TO %06X " % ( self.emu.lastAddress-2 )
                    lastAddressArray[self.emu.lastAddress-2] = True
                 else:
                    lastAddressArray[self.emu.lastAddress] = True
                    
                 
                 self._runTo(lastAddressArray,self.unitTestCallBack)
             
    
    def _runTo(self,to,unitTestCallBack=None):
       
       if self.emu != None :
           self.stop()
           self.running = True
           self.disableActionWidget()
           self.clearDebugListSelectedLine()
           self.tab.SetSelection(Context.TAB_DEBUG) # goto debug tab
           self.threadEngine = PicThreadEngine(self.emu,unitTestCallBack) 
           self.threadEngine.callback = self.callback
           self.threadEngine.runTillAddress = to
           #print "Starting thread"
           self.threadEngine.start() 
           self.statusBar.SetStatusText("Running")  
    
    def toggleBreakPointAtAdr(self,adr):
        if adr != None:
            # self.breakpoints[adr] = not self.breakpoints[adr]
            if self.breakpoints.has_key( adr ):
               del self.breakpoints[adr]
            else:
               self.breakpoints[adr] = True
               
            #if (self.breakpoints[adr]):
            if (self.breakpoints.has_key( adr )):
                mark ="X"
                self.listBreakpoint.InsertStringItem(0,str(adr))
            else:
                mark =""
                # TODO : remove breakpoint from list
                self._removeBreakPointFromList(str(adr))
                
            self.listAsm.SetStringItem(adr,Context.COL_BP,mark)
            if  hasattr(self, "langParser") and self.langParser.adrToLine[adr] != None :
                self.listLang.SetStringItem(self.langParser.adrToLine[adr],Context.COL_BP,mark)
                
                #if (self.breakpoints[adr]):
                if (self.breakpoints.has_key(adr)):
                    tmpText =  self.listLang.GetItem(self.langParser.adrToLine[adr],Context.COL_CODE).GetText()
                    self.listBreakpoint.SetStringItem(0,1,tmpText)
                
            if (self.threadEngine != None):
               self.threadEngine.runTillAddress = self.breakpoints  
               self.clearDebugListSelectedLine()  
    def updateBreakPoints(self):
        self.listBreakpoint.DeleteAllItems()
        for adr in range(0,self.listAsm.GetItemCount()) :
            #if (self.breakpoints[adr]):
            if (self.breakpoints.has_key(adr)):
                mark ="X"
                self.listBreakpoint.InsertStringItem(0,str(adr))
            else:
                mark =""
                # TODO : remove breakpoint from list
                self._removeBreakPointFromList(str(adr))
                
            self.listAsm.SetStringItem(adr,Context.COL_BP,mark)
            if  hasattr(self, "langParser") and self.langParser.adrToLine[adr] != None :
                self.listLang.SetStringItem(self.langParser.adrToLine[adr],Context.COL_BP,mark)
                
                #if (self.breakpoints[adr]):
                if (self.breakpoints.has_key(adr)):
                    tmpText =  self.listLang.GetItem(self.langParser.adrToLine[adr],Context.COL_CODE).GetText()
                    self.listBreakpoint.SetStringItem(0,1,tmpText)
    
    def _removeBreakPointFromList(self,adr):
        lineToRemove = []
        cpt = self.listBreakpoint.GetItemCount()
        for i in range (0,cpt):
            curAdr =  self.listBreakpoint.GetItem(i,0).GetText()
            if curAdr == adr :
                lineToRemove.append(i)
        for i in lineToRemove:
            self.listBreakpoint.DeleteItem(i)
            
            
        
        
    def OnBreakPointAsm(self,event):
        adr = self.listAsm.GetFirstSelected()
        self.toggleBreakPointAtAdr(adr)
        
    def OnBreakPointLang(self,event):
        adr = self.langParser.lineToAdr[self.listLang.GetFirstSelected()]
        self.toggleBreakPointAtAdr(adr)
        
    def OnListLangSelected(self,event):
        self.currentItemDebug = event.m_itemIndex 
        # sync list asm
        item = self.listLang.GetItem(self.currentItemDebug,Context.COL_ADR)
        adr =  item.GetText().strip()
        if (adr != ""):
            self.listAsm.Select(int(adr,16), True)
            self.listAsm.EnsureVisible(int(adr,16))
    #-------------------------------------------------------------------------------
    # Next action
    # 
    def callback(self,adr):
        evtCallBack = self.UpdateCallbackEvent(adr = adr)
        wx.PostEvent(Context.frame, evtCallBack)


        
    def unitTestCallBack(self,address):
        #print "callback for address : "+str(address) 
        label =""
        res= ""
        status = "ERROR"
        item = 0 # insert error on top
        color = "red"
        if address >= len(self.langParser.adrToLine):
            res =  "Address is out of bound [0..8191] : "+str(address)
            status = "ERROR"
            self.listUnitTest.InsertStringItem(item,label)
            self.listUnitTest.SetStringItem(item,1,status)
            self.listUnitTest.SetStringItem(item,2,res)
            self.listUnitTest.SetItemTextColour(item,color)
        else :    
            line = self.langParser.adrToLine[address]
            if line != None:
                code =  self.listLang.GetItem(line,Context.COL_CODE).GetText()
                if "@assertEquals" in code :
                    res = AssertUtil.parse(code)
                    var = res["var"].lower()
                    label = res["label"]
                    ref = res["ref"]
                    if (self.langParser.varAdrMapping.has_key("v_"+var)):
                        varAddr = self.langParser.varAdrMapping["v_"+var]
                        # print self.varTypeDict
                        
                        if self.varTypeDict.has_key( var ):
                            varType = type = self.varTypeDict[var]
                        else:
                            varType = "Unknown type: "
                        
                        val = self.varValue(varAddr,varType)  
                        
                        res= varType+" "+var+" (@"+str(varAddr)+") = 0x%X , expected : 0x%X" %(val,ref)
                        
                        if (ref == val) :
                            status = "PASS"
                            color ="#008000"
                            item = self.listUnitTest.GetItemCount()
                        else :
                            status = "FAIL"
                            
                    else :
                        status = "ERROR"
                        res = "Test can't be run, var "+var+" can't be identified (address not found in asm file)"
                    self.listUnitTest.InsertStringItem(item,label)
                    self.listUnitTest.SetStringItem(item,1,status)
                    self.listUnitTest.SetStringItem(item,2,res)
                    self.listUnitTest.SetItemTextColour(item,color)
                    
   
    def enableActionWidget(self):
        self.bNextLang.Enable()
        self.bNextAsm.Enable()
        self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
        self.top.GetMenuBar().Enable(124,True) # Run Menu
        
        self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
        
        self.top.toolbar.EnableTool(Context.TOOL_COMPILE,True)
        
        self.top.toolbar.EnableTool(Context.TOOL_OPEN,True)
        self.top.toolbar.EnableTool(Context.TOOL_NEW,True)
        self.top.GetMenuBar().Enable(100,True)
        self.top.GetMenuBar().Enable(101,True)
        self.top.GetMenuBar().Enable(103,True)
        


    def disableActionWidget(self):
        if platform.machine()=='i386':
            self.bNextLang.Disable() # TODO : seems not to work well on linux ???
        
        self.bNextAsm.Disable()
        self.top.toolbar.EnableTool(Context.TOOL_RUN,False)
        self.top.GetMenuBar().Enable(124,False) # Run Menu

        self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,False)
        self.top.toolbar.EnableTool(Context.TOOL_COMPILE,False)
        
        self.top.toolbar.EnableTool(Context.TOOL_OPEN,False)
        self.top.toolbar.EnableTool(Context.TOOL_NEW,False)
        self.top.GetMenuBar().Enable(100,False)
        self.top.GetMenuBar().Enable(101,False)
        self.top.GetMenuBar().Enable(103,False)

        
        
    def clearDebugListSelectedLine(self):
       if hasattr(self, "listLang") : 
           item = self.listLang.GetFirstSelected()
           if item != -1:     
               self.listLang.Select(item,False)  
           while item != -1:
                item = self.listLang.GetNextSelected(item)
                self.listLang.Select(item,False)
           
       item = self.listAsm.GetFirstSelected()
       if item != -1:         
           self.listAsm.Select(item,False)
       
    def gotoTopDebugList(self):
       if hasattr(self, "listLang") :
           self.listLang.Select(0,True)
           self.listLang.EnsureVisible(0)
      
       self.listAsm.Select(0,True)
       self.listAsm.EnsureVisible(0)
       
    #----------------------------------------------------------------
    # Lists (ASM AND LANG)
    #
    def updateDebugListPosition(self,adr):
        self.clearDebugListSelectedLine()
        self.listAsm.Select(adr, True)
        self.listAsm.EnsureVisible(long(adr))
        if hasattr(self, "langParser"):
            langLine = self.langParser.adrToLine[adr]
            
            if (langLine != None):
                self.listLang.Select(langLine, True)
                nbLines = self.listLang.GetItemCount() 
                for i in range(langLine,nbLines):
                    nextadr =  self.listLang.GetItem(i,Context.COL_ADR).GetText()
                    try :
                        nextadr = int(nextadr,16)
                        if adr == nextadr:
                            self.listLang.Select(i, True)
                        else:
                            break
                    except :
                        break
                self.listLang.EnsureVisible(long(langLine))
    
    def loadDebugList(self,instructionList,lastAddress,code,wholeCode):
        self.listAsm.DeleteAllItems()
        if code != None:
            self.listLang.DeleteAllItems()
        
        # fill asm list
        for i in range(0,lastAddress+1):
            inst = instructionList[i]
            self.listAsm.InsertStringItem(i, "")
            self.listAsm.SetStringItem(i,Context.COL_ADR,  "%06X" % inst.adresse )
            self.listAsm.SetStringItem(i,Context.COL_CODE, Format.formatInstructionWithoutAddress(inst, 0, True).strip())
            #print str(inst.adresse)+" "+Format.formatInstructionWithoutAddress(inst, 0, False).strip()
            
    
        # decorate with jal comment
        for i in range (0,len(wholeCode)):
           if (wholeCode[i] != None):
               if (self.asmParser.lineToAdr[i] != None):
                  
                      text = wholeCode[i].line
                      tmpText =  self.listAsm.GetItem(self.asmParser.lineToAdr[i],Context.COL_COM).GetText()
                      if (tmpText.strip() != ''):
                          try :
                              text = unicode(tmpText+" / "+wholeCode[i].line)
                          except : 
                              print "Warning : Exception occurs in UIManager.loadDebugList on text :"
                              print tmpText,
                              print " / ",
                              print wholeCode[i].line
                      try :        
                          self.listAsm.SetStringItem(self.asmParser.lineToAdr[i],Context.COL_COM,text.replace("\t","    ")) 
                      except :
                          first_error = False
                          # something got wrong...
                          print "======================================================="
                          print "Error in UIManager.loadDebugList(...)"
                          print i        
                          print text
                          print "Unreachable adress : "+str(self.asmParser.lineToAdr[i])
                          print "======================================================="
                          
        if code != None :      
            # fill lang list

            self.allLineAddresses =  {}

            for i in range (0,len(code)):
               if (code[i] != None):
                  #print "PL : " code[i].line
                  self.listLang.InsertStringItem(i,"") # breakpoint
                  if code[i].address != " ":
                      # print ":" + code[i].address + ":"
                      self.listLang.SetStringItem(i,Context.COL_ADR, "%06X" % code[i].address)
                  else:
                      self.listLang.SetStringItem(i,Context.COL_ADR, "")
                      
                  self.listLang.SetStringItem(i,Context.COL_CODE, code[i].line.replace("\t","    "))
                  
                  if code[i].address != " ":
                      self.allLineAddresses[code[i].address] = True
                     
                  curLine = self.listLang.GetItem(i,Context.COL_CODE).GetText()
                  upCurLine = curLine.upper()
                  if (curLine.startswith('--')):
                      self.listLang.SetItemTextColour(i,'#55CC55')
                  elif ('PROCEDURE' in upCurLine)  or ('FUNCTION' in upCurLine) or ('LOOP' in upCurLine) or ('IF ' in upCurLine) or ('ELSE' in upCurLine) or ('END ' in upCurLine):
                      font = self.listLang.GetItemFont(i)
                      font.SetWeight(wx.BOLD)
                      font.SetPointSize(8)
                      self.listLang.SetItemFont(i,font)
                      # set asm list boldness
                      try :
                          self.listAsm.SetItemFont(self.langParser.lineToAdr[i],font)
                      except : pass

    
    def OnVarFilterKeyDown(self,event):
        if self.listWatchVars.GetItemCount() > 0:
            self.updateWatchVarView()
    def OnRegFilterKeyDown(self,event):
        if self.listWatchRegs.GetItemCount() > 0:
            self.updateWatchRegView()
            
    def OnEEPromFilterKeyDown(self,event):
        if hasattr(self.emu, "state") :
            self.updateWatchDataEEPromView()
    
    #----------------------------------------------------------------
    # Watched Regs / Vars
    #
    def updateWatchVarView(self):   
        format4 ="%4d"
        format2 = "0x%02X"
        self.listWatchVars.DeleteAllItems()
    
        # display var list
        self.listWatchVars.InsertStringItem(0,"PC")
        self.listWatchVars.SetStringItem(0,2, format2  %self.emu.state.getPc())
        
        font = self.listWatchVars.GetItemFont(0)
        font.SetWeight(wx.BOLD)
        self.listWatchVars.InsertStringItem(1,"W")
        self.listWatchVars.SetStringItem(1,2, format2 % self.emu.state.getW())
        self.listWatchVars.InsertStringItem(2,"STATUS")
        self.listWatchVars.SetStringItem(2,2, Format.binf(self.emu.state.getStatus()))
        self.listWatchVars.SetItemFont(0,font)
        self.listWatchVars.SetItemFont(1,font)
        self.listWatchVars.SetItemFont(2,font)
        index = 3
        if hasattr(self,"langParser"):
            for var in sorted(self.langParser.varAdrMapping):
                varDispType ="h:"
                varName = var.replace("v_","")
                show = False
                filters = self.varFilter.GetValue()
                if (filters.strip() != ""):
                    for filter in filters.split(","):
                        filter = filter.strip()
                        filter = filter.upper()
                        
                        if filter.startswith("B:"):
                            filter = filter[2:]
                            varDispType="b:"
                        elif filter.startswith("H:") or filter.startswith("0X"):
                            filter = filter[2:]
                            varDispType="h:"
                        elif filter.startswith("D:"):
                            filter = filter[2:]
                            varDispType="d:"
                        
                        if varName.upper().startswith(filter):
                            show = True
                else:
                    show =True
                
                if (show):
                    self.listWatchVars.InsertStringItem(index,varName)
                    adr = self.langParser.varAdrMapping[var]
                    
                    type= ""

                    if hasattr(self, "varTypeDict") and self.varTypeDict != None and self.varTypeDict.has_key(varName):
                        type = self.varTypeDict[varName]
                    else:
                        type = "? (byte)"
                    type = type.upper()  
                    self.listWatchVars.SetStringItem(index,1,type )
                    
                    # BIT - 1 bit
                    # BYTE - 8 bit, unsigned
                    # SBYTE - 8 bit, signed
                    # WORD - 16 bit, unsigned
                    # SWORD - 16 bit, signed
                    # DWORD - 32 bit, unsigned
                    # SDWORD - 32 bit, signed
                    # user defined : [S]BYTE*n, creates an n-BYTE signed            
                    
                    val = self.varValue(adr,type)  
                    valAsStr = str(val)
                    if (varDispType =="b:") :
                        valAsStr = Format.binf(val)
                    if (varDispType =="h:") :
                        valAsStr = "0x%X" % val
                    
                        
                    self.listWatchVars.SetStringItem(index,2,valAsStr )
                    self.listWatchVars.SetStringItem(index,3,format2 % adr )
                    
                    # Highlight changes
                    changed = True
                    if self.oldWatchedVars.has_key(var):
                        if val != self.oldWatchedVars[var]:
                            changed = True
                        else:
                            changed = False
                    if changed :
                        self.listWatchVars.SetItemTextColour(index,"#FF0000")
                    else:
                        self.listWatchVars.SetItemTextColour(index,"#000000")
                    self.oldWatchedVars[var] = val
                    index +=1

    def varValue(self,adr,type):
        type = type.upper()
        if type == "WORD":
            type = "BYTE*2"
        elif type == "DWORD":
            type = "BYTE*4"
        elif type == "BIT":
            pass
        elif type == "SBYTE":
            type = "SBYTE*1"
        elif type == "SWORD":
           type="SBYTE*2"
        elif type == "SDWORD":
            type="SBYTE*4"
            
        if "*" in type:
            parts = type.split("*")
            num = int(parts[1]) 
            format = "%02X" * num
            params = []
            for i in range (num-1,-1,-1):
                params.append(self.emu.state.absreg(adr+i))
            word = format % tuple(params)
            wordVal = int (word,16)
            if parts[0] == "SBYTE":
                sign = self.emu.state.absreg(adr+num-1) >> 7
                wordVal = int (word,16)
                if sign > 0:
                    #neg
                    max = pow(2,num*8)
                    wordVal = max - wordVal
                    wordVal *= -1
            
            val = wordVal
        else:
            val = self.emu.state.absreg(adr)
        return val
                            
    # -------------------------------------------------------------------------
    #
    #
    def updateWatchRegView(self):
        self.listWatchRegs.DeleteAllItems()
        format4 ="%4d"
        format2 = "0x%02X"
        self.listWatchRegs.InsertStringItem(0,"PC")
        self.listWatchRegs.SetStringItem(0,1, "0x%X"  % self.emu.state.getPc())
        self.listWatchRegs.SetStringItem(0,2, "%d"  % self.emu.state.getPc())
        
        font = self.listWatchRegs.GetItemFont(0)
        font.SetWeight(wx.BOLD)
        self.listWatchRegs.InsertStringItem(1,"W")
        self.listWatchRegs.SetStringItem(1,1, format2 % self.emu.state.getW())
        self.listWatchRegs.SetStringItem(1,2, format4 % self.emu.state.getW())
        
        self.listWatchRegs.InsertStringItem(2,"STATUS")        
        statusValue = self.emu.state.getStatus()
        self.listWatchRegs.SetStringItem(1,2, format4 % statusValue )
        
        bs = Format.bin(statusValue)
        status="IRP=%s, RP1=%s, RP0=%s, TO=%s" %(bs[0],bs[1],bs[2],bs[3])
        status2="PD=%s, Z=%s, DC=%s, C=%s" %(bs[4],bs[5],bs[6],bs[7])
        self.listWatchRegs.SetStringItem(2,2, status)
        self.listWatchRegs.InsertStringItem(3,"")
        self.listWatchRegs.SetStringItem(3,2, status2)
        
        self.listWatchRegs.SetItemFont(0,font)
        self.listWatchRegs.SetItemFont(1,font)
        self.listWatchRegs.SetItemFont(2,font)
        self.listWatchRegs.SetItemFont(3,font)
        index = 4

        regs = set()
        regsType = {}
        filters = self.regFilter.GetValue()
        regTxt = []
        if (filters.strip() != ""):
            regTxt = filters.split(",")
        
        
        #--------------------------------------
        # Main reg param loop
        
        for reg in regTxt :
            if reg != "":
                if reg.upper().startswith("B:"):
                    reg = reg[2:]
                    try:
                        parts = reg.split("..")
                        regsType[Format.toNumber(parts[0])] ="b:"
                    except : pass
                elif reg.upper().startswith("H:"):
                    reg = reg[2:]
                    try:
                        parts = reg.split("..")
                        regsType[Format.toNumber(parts[0])] ="h:"
                    except : pass
                elif reg.upper().startswith("D:"):
                    reg = reg[2:]
                    try:
                        parts = reg.split("..")
                        regsType[Format.toNumber(parts[0])] ="d:"
                    except : pass
                else :
                    try:
                        parts = reg.split("..")
                        regsType[Format.toNumber(parts[0])] ="h:"
                    except : pass
                try :
                    if ".." in reg:
                        parts = reg.split("..")
                        n1 = Format.toNumber(parts[0])
                        n2 = Format.toNumber(parts[1])+1
                        for val in range (n1,n2):
                            if val <= (0x1FF):
                                regs.add(val)
                                regsType[val] =regsType[n1]
                                
                    elif "*" in reg :
                        regs.add(reg)
                    else:
                        val = Format.toNumber(reg)
                        if val <= (0x1FF):
                            regs.add(val)
                except  :
                    #print sys.exc_info()[0]
                    pass # something wrong entred ? TODO : message
        regs = list(regs)
        regs.sort()
        wregs = list(self.watchedReg)
        wregs.sort()
        regs += ["-"]+wregs       
        for reg in regs :
            
            if reg == "-":
                self.listWatchRegs.InsertStringItem(index,"-"*10)
                self.listWatchRegs.SetStringItem(index,1, "-"*10)
                self.listWatchRegs.SetStringItem(index,2, "-"*20)
            else:
                
                # multi byte mode
                parts = str(reg).split("*")
                nReg = 0
                if (len(parts)==2) and parts[1] != "":
                    
                    startReg= Format.toNumber(parts[0])
                    nbBytes = int(parts[1])
                    vReg ="b"
                    if nbBytes == 0:
                        nbBytes = 1   
                    for i in range(startReg+nbBytes-1,startReg-1,-1):
                        vReg += Format.bin(self.emu.state.absreg(i))
                    format ="%d"
                    if parts[0].startswith("0x"):
                        format = "0x%X"
                    nReg = Format.toNumber(vReg)
                    vReg = format  % nReg
                    regStr = reg
                else :
                    nReg = self.emu.state.absreg(Format.toNumber(parts[0]))
                    vReg =  format2 % nReg
                    regStr = "%4d 0x%03X" % (Format.toNumber(parts[0]),Format.toNumber(parts[0]))
                
                # if prefix avaiable("b:"), override default display
                
                if (regsType.has_key(reg)):
                    if(regsType[reg]=="d:"):
                        vReg =str(nReg)
                    elif(regsType[reg]=="b:"):
                        vReg =Format.binf(nReg)
                    elif(regsType[reg]=="h:"):
                        vReg = "0x%X"  % nReg    
                    
                #---------------------------
                # display
                
                self.listWatchRegs.InsertStringItem(index,regStr)
                self.listWatchRegs.SetStringItem(index,1, vReg)
                comment =""
                
                if hasattr(self, "langParser") and (self.langParser.adrVarMapping.has_key(reg)):
                    comment =self.langParser.adrVarMapping[reg]
                    comment = comment.replace("v_","")
                tmp = "?"
                try:
                    tmp = regStr.strip().split(" ")[0]
                    nReg = int(tmp)
                    #if (Format.spAdrReg.has_key(nReg)) :
                    #    comment = Format.spAdrReg[nReg]
                    if ( self.emu.state.spAdrReg.has_key(nReg)) :
                        comment = self.emu.state.spAdrReg[nReg]
                except :
                    #print "UIManager.updateWatchRegView : ["+tmp+"]"
                    pass
                self.listWatchRegs.SetStringItem(index,2, comment)
                changed = True
                if self.oldWatchedValues.has_key(str(reg)):
                    if vReg != self.oldWatchedValues[str(reg)]:
                        changed = True
                    else:
                        changed = False
                if changed :
                    self.listWatchRegs.SetItemTextColour(index,"#FF0000")
                else:
                    self.listWatchRegs.SetItemTextColour(index,"#000000")
                self.oldWatchedValues[str(reg)] = vReg
            index += 1

    # -----------------------------------------------------------------------------
    #
    #

    def updateWatchDataEEPromView(self):
        #format4 ="%4d"
        format2 = "0x%02X"
        #--------------------------------------------
        # display regs to watch
        # reg get added when state.regWrite() by the RegisterUpdater class
        self.listWatchDataEEProm.DeleteAllItems()
        addrs = set()
        filters = self.dataEEPromFilter.GetValue()
        addrTxt = []
        if (filters.strip() != ""):
            addrTxt = filters.split(",")
        for addr in addrTxt :
            if addr != "":
                try :
                    if ".." in addr:
                        parts = addr.split("..")
                        n1 = Format.toNumber(parts[0])
                        n2 = Format.toNumber(parts[1])+1
                        for val in range (n1,n2):
                            if val <= (0xFF):
                                addrs.add(val)    
                    else:
                        val = Format.toNumber(addr)
                        if val <= (0xFF):
                            addrs.add(val)
                except : pass # something wrong entred ? TODO : message
        addrs = list(addrs)
        addrs.sort()
        
        for i,adr in enumerate(addrs) :
            self.listWatchDataEEProm.InsertStringItem(i,str(adr))
            val = format2  % self.emu.state.eeData[adr]
            self.listWatchDataEEProm.SetStringItem(i,1,val)
            

    def OnRemoveAllBreakpoints(self,event):
        self.removeAllBreakpoints()
        
    def removeAllBreakpoints(self):
        # clear bp
        #for i in range(0,len( self.breakpoints ) ):
        #    self.breakpoints[i] = False  
        #for i in range(0,len( self.breakpoints ) ):
        self.breakpoints = {}

        # remove marks
        nb = self.listLang.GetItemCount()
        for i in range (0,nb):
            self.listLang.SetStringItem(i,Context.COL_BP,"")
        nb = self.listAsm.GetItemCount()
        for i in range (0,nb):
            self.listAsm.SetStringItem(i,Context.COL_BP,"")
        
        #clear list
        self.listBreakpoint.DeleteAllItems()
    
    
    def OnlistBreakPointSelected(self,event):
        currentItem = event.m_itemIndex
        adr =  self.listBreakpoint.GetItem(currentItem,0).GetText()
        line = None
        if hasattr(self, "langParser") : 
            line = self.langParser.adrToLine[int(adr)]
        self.clearDebugListSelectedLine()
       
        if  line != None :
            self.listLang.Select(line, True)
            self.listLang.EnsureVisible(line)
        else:
            self.listAsm.Select(int(adr), True)
            self.listAsm.EnsureVisible(int(adr))
  
    def findReplace(self):
        pageNumber = self.tab.GetSelection()
        dlg = None
        if pageNumber == Context.TAB_EDIT :
            dlg = FindDialog(self.mainEditor, -1, "Find/Replace",style = wx.DEFAULT_DIALOG_STYLE)
        if pageNumber == Context.TAB_BROWSER :
            dlg = FindDialog(self.browserEditor, -1, "Find/Replace",style = wx.DEFAULT_DIALOG_STYLE)
        if dlg != None:    
            dlg.CenterOnScreen()
            dlg.Show()
    def findPinMapping(self):
            res =""
            allLines = self.mainEditor.GetText().split("\n")
            res+="-- ---------------------------------\n"  
            res+="-- Pin and Port Direction\n"  
            res+="-- ---------------------------------\n"  
            i=0
            for line in allLines :
                i += 1
                lc = line.upper()
                lc = lc.replace("--",";")
                lc = lc.split(";")[0]
                if "_DIRECTION" in lc :
                    res+= str(i)+": "+line+"\n"

            res+="-- ---------------------------------\n"  
            res+="-- Pin and Port Alias\n"  
            res+="-- ---------------------------------\n"  
            i=0
            for line in allLines :
                i += 1
                lc = line.upper()
                lc = lc.replace("--",";")
                lc = lc.split(";")[0]
               
                if " IS " in lc :
                    res+= str(i)+": "+line+"\n"
                
            res+="-- ---------------------------------\n"  
            res+="-- Pin and Port usage without alias\n"  
            res+="-- ---------------------------------\n"  
            i = 0
            for line in allLines :
                i += 1
                lc = line.strip().upper()
                lc = lc.replace("--",";")
                lc = lc.split(";")[0]
               
                if " IS " in lc :
                    pass
                elif "_DIRECTION" in lc :
                    pass
                elif "PIN_" in lc :
                    res+=str(i)+": "+line+"\n"
                elif re.search("[\t\)\n ]?PORT[ABCDE]\W",lc) :
                    res+=str(i)+": "+line+"\n"
          
            self.helpText.SetText(res)

  
    def importHex(self,filename=""):
        if filename=="":
            filename = FileUtil.open("*.hex")
        if filename != "":
            self.newProject()
            self.buildEmu(filename)
            self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
            self.top.GetMenuBar().Enable(124,True)
            self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
            self.loadDebugList(self.emu.instructionList,self.emu.lastAddress,None,[])
            self.tab.SetSelection(Context.TAB_DEBUG) # goto debug tab

        annotationsFilename = filename.replace(".hex",".txt")
        if os.path.exists(annotationsFilename):
            self.openEditor(Context.TAB_EDIT, annotationsFilename, False)
            parseRes = AnnotationParser.parse(self.mainEditor.GetText())
            self.buildInOut(parseRes["inputs"],parseRes["outputs"])

    def showPreferences(self):
        dlg = PreferencesDialog(self.mainEditor, -1, "Preferences",style = wx.DEFAULT_DIALOG_STYLE)
        dlg.CenterOnScreen()
        dlg.ShowModal()
        dlg.Destroy()
        
    #----------------------------------------------------------------
    # Log a message
    #
    def log(self,message):
        print message
        
    #
    # export a file and its dependencies in a single zip file
    #
    def exportBundle(self):
        mainfile = self.getEditor(Context.TAB_EDIT).filename
        if mainfile =="" :
            wx.MessageBox("Unable to get current file name")
            return
       
        defaultname = os.path.basename(mainfile).split(".jal")[0]
        allincludes = EditorUtil.findAllIncludedFiles(self.mainEditor.GetText(),os.path.dirname(mainfile)+";"+Context.libpath)
       
        dlg = wx.FileDialog(Context.top,"Choose a file", Context.sourcepath, defaultname+".zip", "*.zip", wx.SAVE)
        if dlg.ShowModal() == wx.ID_OK:
            zipfilename = dlg.GetPath()
            dlg.Destroy()
            if wx.Platform == '__WXMSW__':
                self.zipWin(mainfile,zipfilename,allincludes)
            else :
                self.zipUnix(mainfile,zipfilename,allincludes)
    
    
    def zipUnix(self,mainfile,zipfilename,allincludes):
        
        f = ZipFile(zipfilename,"w")
        self.compileTab.SetSelection(Context.COMPILE_RESULT_TAB)
        self.compileLog.Clear()
        self.compileLog.AppendText("Creating bundle zip file :"+zipfilename+"\n")
        f.writestr("README.txt", "")
        f.close()  
        # Main file
        self.compileLog.AppendText("  adding file : "+mainfile)
        try :
             cmd ="zip -j "+zipfilename+" "+mainfile
             os.system(cmd)
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
         
        # includes
        for inc in allincludes :
            self.compileLog.AppendText("  adding file : "+inc)
            try :
                cmd ="zip -j "+zipfilename+" "+inc
                os.system(cmd)
            except Exception, err:
                self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
            self.compileLog.AppendText("\n")
            
        self.compileLog.AppendText("Completed.\n")
        
                    
    def zipWin(self,mainfile,zipfilename,allincludes):
        maindir = os.path.basename(mainfile).split(".jal")[0]
        f = ZipFile(zipfilename,"w")
        self.compileTab.SetSelection(Context.COMPILE_RESULT_TAB)
        self.compileLog.Clear()
        self.compileLog.AppendText("Creating bundle zip file :"+zipfilename+"\n")
       
        maindir += os.path.sep
       
        # Compiler
        compiler = Context.compiler
        
        if not compiler.endswith(".exe") :
            compiler+=".exe"
        
        destFile = maindir+"compiler"+os.path.sep+os.path.basename(compiler)
        
        self.compileLog.AppendText("  adding file : "+compiler+" as "+destFile)        
        try :
            f.write(compiler,destFile)
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
       
       # README.txt
        self.compileLog.AppendText("  adding file : "+maindir+"README.txt")
        try :
            f.writestr(maindir+"README.txt", "compiler"+os.path.sep+os.path.basename(compiler)+" -s lib "+Context.compilerOptions+" "+os.path.basename(mainfile))
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
            
        # Main file
        destFile = maindir+os.path.basename(mainfile)
        self.compileLog.AppendText("  adding file : "+mainfile+" as "+destFile)
        try :
            f.write(mainfile,destFile)
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
        
        # includes
        for inc in allincludes :
            destFile = maindir+"lib"+os.path.sep+os.path.basename(inc)
            self.compileLog.AppendText("  adding file : "+inc+" as "+destFile)
            try :
                #print "basname :" + os.path.basename(inc) + ":"
                f.write(inc,destFile) #cp437
                #f.write(inc,os.path.basename(inc)) #cp437
            except Exception, err:
                self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
            self.compileLog.AppendText("\n")
            
        self.compileLog.AppendText("Completed.\n")
        f.close()